﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace AdvancedDataGridView
{
	public class TreeGridCell : DataGridViewTextBoxCell
	{
		public TreeGridCell()
		{
			this.glyphWidth = 0;
			this.calculatedLeftPadding = 0;
			this.IsSited = false;
		}

		public override object Clone()
		{
			TreeGridCell treeGridCell = (TreeGridCell)base.Clone();
			treeGridCell.glyphWidth = this.glyphWidth;
			treeGridCell.calculatedLeftPadding = this.calculatedLeftPadding;
			return treeGridCell;
		}

		protected internal virtual void UnSited()
		{
			this.IsSited = false;
			base.Style.Padding = this._previousPadding;
		}

		protected internal virtual void Sited()
		{
			this.IsSited = true;
			this._previousPadding = base.Style.Padding;
			this.UpdateStyle();
		}

		protected internal virtual void UpdateStyle()
		{
			if (this.IsSited)
			{
				int level = this.Level;
				Padding previousPadding = this._previousPadding;
				Size preferredSize;
				using (Graphics graphics = this.OwningNode._grid.CreateGraphics())
				{
					preferredSize = this.GetPreferredSize(graphics, base.InheritedStyle, base.RowIndex, new Size(0, 0));
				}
				Image image = this.OwningNode.Image;
				if (image != null)
				{
					this._imageWidth = image.Width + 2;
					this._imageHeight = image.Height + 2;
				}
				else
				{
					this._imageWidth = this.glyphWidth;
					this._imageHeight = 0;
				}
				if (preferredSize.Height < this._imageHeight)
				{
					base.Style.Padding = new Padding(previousPadding.Left + level * 20 + this._imageWidth + 5, previousPadding.Top + this._imageHeight / 2, previousPadding.Right, previousPadding.Bottom + this._imageHeight / 2);
					this._imageHeightOffset = 2;
				}
				else
				{
					base.Style.Padding = new Padding(previousPadding.Left + level * 20 + this._imageWidth + 5, previousPadding.Top, previousPadding.Right, previousPadding.Bottom);
				}
				this.calculatedLeftPadding = (level - 1) * this.glyphWidth + this._imageWidth + 5;
			}
		}

		public int Level
		{
			get
			{
				TreeGridNode owningNode = this.OwningNode;
				int result;
				if (owningNode != null)
				{
					result = owningNode.Level;
				}
				else
				{
					result = -1;
				}
				return result;
			}
		}

		protected virtual int GlyphMargin
		{
			get
			{
				return (this.Level - 1) * 20 + 5;
			}
		}

		protected virtual int GlyphOffset
		{
			get
			{
				return (this.Level - 1) * 20;
			}
		}

		protected override void Paint(Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
		{
			TreeGridNode owningNode = this.OwningNode;
			if (owningNode != null)
			{
				Image image = owningNode.Image;
				if (this._imageHeight == 0 && image != null)
				{
					this.UpdateStyle();
				}
				base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
				System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(cellBounds.X + this.GlyphMargin, cellBounds.Y, 20, cellBounds.Height - 1);
				int num = rectangle.Width / 2;
				int level = this.Level;
				if (image != null)
				{
					System.Drawing.Point point;
					if (this._imageHeight > cellBounds.Height)
					{
						point = new System.Drawing.Point(rectangle.X + this.glyphWidth, cellBounds.Y + this._imageHeightOffset);
					}
					else
					{
						point = new System.Drawing.Point(rectangle.X + this.glyphWidth, cellBounds.Height / 2 - this._imageHeight / 2 + cellBounds.Y);
					}
					GraphicsContainer container = graphics.BeginContainer();
					graphics.SetClip(cellBounds);
					graphics.DrawImageUnscaled(image, point);
					graphics.EndContainer(container);
				}
				if (owningNode._grid.ShowLines)
				{
					using (Pen pen = new Pen(SystemBrushes.ControlDark, 1f))
					{
						pen.DashStyle = DashStyle.Dot;
						bool isLastSibling = owningNode.IsLastSibling;
						bool isFirstSibling = owningNode.IsFirstSibling;
						if (owningNode.Level == 1)
						{
							if (isFirstSibling && isLastSibling)
							{
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.Right, cellBounds.Top + cellBounds.Height / 2);
							}
							else if (isLastSibling)
							{
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.Right, cellBounds.Top + cellBounds.Height / 2);
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2);
							}
							else if (isFirstSibling)
							{
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.Right, cellBounds.Top + cellBounds.Height / 2);
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.X + 4, cellBounds.Bottom);
							}
							else
							{
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.Right, cellBounds.Top + cellBounds.Height / 2);
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top, rectangle.X + 4, cellBounds.Bottom);
							}
						}
						else
						{
							if (isLastSibling)
							{
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.Right, cellBounds.Top + cellBounds.Height / 2);
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2);
							}
							else
							{
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top + cellBounds.Height / 2, rectangle.Right, cellBounds.Top + cellBounds.Height / 2);
								graphics.DrawLine(pen, rectangle.X + 4, cellBounds.Top, rectangle.X + 4, cellBounds.Bottom);
							}
							TreeGridNode parent = owningNode.Parent;
							int num2 = rectangle.X + 4 - 20;
							while (!parent.IsRoot)
							{
								if (parent.HasChildren && !parent.IsLastSibling)
								{
									graphics.DrawLine(pen, num2, cellBounds.Top, num2, cellBounds.Bottom);
								}
								parent = parent.Parent;
								num2 -= 20;
							}
						}
					}
				}
				if (owningNode.HasChildren || owningNode._grid.VirtualNodes)
				{
					if (owningNode.IsExpanded)
					{
						owningNode._grid.rOpen.DrawBackground(graphics, new System.Drawing.Rectangle(rectangle.X, rectangle.Y + rectangle.Height / 2 - 4, 10, 10));
					}
					else
					{
						owningNode._grid.rClosed.DrawBackground(graphics, new System.Drawing.Rectangle(rectangle.X, rectangle.Y + rectangle.Height / 2 - 4, 10, 10));
					}
				}
			}
		}

		protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
		{
			base.OnMouseUp(e);
			TreeGridNode owningNode = this.OwningNode;
			if (owningNode != null)
			{
				owningNode._grid._inExpandCollapseMouseCapture = false;
			}
		}

		protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
		{
			if (e.Location.X > base.InheritedStyle.Padding.Left)
			{
				base.OnMouseDown(e);
			}
			else
			{
				TreeGridNode owningNode = this.OwningNode;
				if (owningNode != null)
				{
					owningNode._grid._inExpandCollapseMouseCapture = true;
					if (owningNode.IsExpanded)
					{
						owningNode.Collapse();
					}
					else
					{
						owningNode.Expand();
					}
				}
			}
		}

		public TreeGridNode OwningNode
		{
			get
			{
				return base.OwningRow as TreeGridNode;
			}
		}

		private const int INDENT_WIDTH = 20;

		private const int INDENT_MARGIN = 5;

		private int glyphWidth;

		private int calculatedLeftPadding;

		internal bool IsSited;

		private Padding _previousPadding;

		private int _imageWidth = 0;

		private int _imageHeight = 0;

		private int _imageHeightOffset = 0;

		private System.Drawing.Rectangle _lastKnownGlyphRect;
	}
}
